/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package aiaudio.processing.ratings.inverse;

import aiaudio.processing.base.mapreduce.UserValuePair;
import aiaudio.Application;
import aiaudio.database.tablegroup.InitialDataTableGroup;
import aiaudio.database.tables.ArtistsListTable;
import aiaudio.database.tables.DataMetricsTable;
import aiaudio.database.tables.RatingsMatrixTable;
import java.io.IOException;
import org.apache.hadoop.hbase.client.HTable;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.hadoop.hbase.mapreduce.TableReducer;
import org.apache.hadoop.mapreduce.Reducer;

/**
 *
 * @author nastya
 */
class RatingInversionReducer extends TableReducer<ImmutableBytesWritable, UserValuePair, ImmutableBytesWritable> {
    private long fullUserCount;

    protected long getCountOfUserVoting(ImmutableBytesWritable key) throws IOException {
        String artists = InitialDataTableGroup.getInstance().getArtistsTable();
        HTable artistsTable = Application.database().getByName(artists).getTable();
        return ArtistsListTable.getVotingCount(artistsTable, key.get());
    }

    @Override
    protected void setup(Context context) throws IOException, InterruptedException {
        super.setup(context);
        String dm = InitialDataTableGroup.getInstance().getDataMetricsTable();
        HTable dataMetricsTable = Application.database().getByName(dm).getTable();
        fullUserCount = DataMetricsTable.getUsersCount(dataMetricsTable);
    }

    @Override
    protected void reduce(ImmutableBytesWritable key, Iterable<UserValuePair> values, Context context) throws IOException, InterruptedException {
        long userVoting = getCountOfUserVoting(key);
        double multiplexor = userVoting == 0 ? Double.NaN : Math.log(fullUserCount / userVoting);
        Put put = new Put(key.get());
        for (UserValuePair valueKeyUser : values) {
            double result = valueKeyUser.getValue() * multiplexor;
            RatingsMatrixTable.addUserRating(put, valueKeyUser.getUser(), result);
        }
        RatingsMatrixTable.addDefaultRating(put, 0.0);
        context.write(key, put);
    }
    
}
